/**
 * @file TcpServer.h
 * @author huangxiaozhu (xiaozhuhuang2014@163.com)
 * @brief  TcpServer服务端
 * @version 1.0.0
 * @date 2024-02-26
 * 
 * @copyright Copyright (c) 2024
 * 
 */

#pragma once

#include "tools/CommonServer/CommonServer.h"
#include "Session.h"
#include <boost/thread.hpp>
#include <unordered_map>

class TcpServer;
using TcpServerPtr = std::shared_ptr<TcpServer>;


class TcpServer : public CommonServer, public std::enable_shared_from_this<TcpServer>
{
public:
    TcpServer() = default;
    TcpServer(short port, int threadCount = 1);
    ~TcpServer();

    virtual void Start() override;                  // 启动tcp服务器，模式使用单线程
    virtual void Stop() override;

    // socket相关的接口
    void StartAccept();
    void HandleAccept(TcpSocketPtr socket, const boost::system::error_code &ec);

    void SendTo(const std::string& name, const std::string& message);
    void SendToAll(const std::string& message);

    // Session管理接口
    bool AddSession(std::shared_ptr<Session> session);
    void DeleteSession(const std::string& name);
    void DeleteAllSession();
    std::shared_ptr<Session> GetSession(const std::string& name);

    void OnSessionClose(const std::string& name);   // 关闭session时回调函数

    template <typename T>
    bool RegisterSessionType()
    {
        if (std::is_base_of<Session, T>::value)
        {
            m_createSessionObjFunc = NewSessionObjFunc<T>;
            return true;
        }
        return false;
    }

protected:
    void RunIoContext();

private:
    boost::asio::io_context m_ioContext;
    tcp::acceptor m_acceptor;

    std::mutex m_sessionMapLock;                                                // session列表操作锁
    std::unordered_map<std::string, std::shared_ptr<Session>> m_sessionMap;

    bool m_beStop = false;                                                      // 停止服务
    boost::thread_group m_threads;                                              // ioContext处理的线程池
    int m_threadCount = 1;                                                      // ioContext处理的线程数

    CreateSessionObjFunc m_createSessionObjFunc = NewSessionObjFunc<Session>;   // 设置创建Session的函数
};